#define _CRT_SECURE_NO_WARNINGS 1
//
//typedef unsigned int uint;
//typedef int* ptr_t;
//
//
//typedef void(*pf_t)(int);
//
//int main()
//{
//	//pf_t p1;
//	//void(* p2)(int);
//
//	//int* p;
//	//ptr_t p2;
//
//	//uint a = 0;
//	//unsigned int b = 0;
//
//	void (* signal( int, void(*)(int) ) )(int);
//	pf_t signal(int, pf_t);
//
//	//void (*)(int) signal(int, void(*)(int));//err
//
//	return 0;
//}
//

//typedef int(*parr_t)[6] ;
//
//int main()
//{
//	int arr[6];
//	int (*p1)[6] = &arr;
//	parr_t p2 = &arr;
//
//
//	return 0;
//}


//int Add(int x, int y)
//{
//	return x + y;
//}
//
//int Sub(int x, int y)
//{
//	return x - y;
//}
//
//int main()
//{
//	int* arr[10];//整型指针的数组
//	//函数指针数组
//	/*int (* p1)(int,int) = Add;
//	int (* p2)(int,int) = Sub;*/
//
//	//函数指针数组 - 存放函数指针的数组
//	int (* pArr[4])(int, int) = {Add, Sub};
//
//	return 0;
//}
//
//
//#include <stdio.h>
//
//int Add(int x, int y)
//{
//	return x + y;
//}
//
//int Sub(int x, int y)
//{
//	return x - y;
//}
//
//int Mul(int x, int y)
//{
//	return x * y;
//}
//
//int Div(int x, int y)
//{
//	return x / y;
//}
//
//
//void menu()
//{
//	printf("***************************\n");
//	printf("*****  1. add  2.sub  *****\n");
//	printf("*****  3. mul  4.div  *****\n");
//	printf("*****  0. exit        *****\n");
//	printf("***************************\n");
//}
//
//void calc(int(*pf)(int, int))
//{
//	int x = 0;
//	int y = 0;
//	int ret = 0;
//
//	printf("请输入2个操作数:>");
//	scanf("%d %d", &x, &y);
//	ret = pf(x, y);
//	printf("%d\n", ret);
//}
//
//int main()
//{
//	int input = 0;
//
//	do
//	{
//		menu();
//		printf("请选择:>");
//		scanf("%d", &input);
//		switch (input)
//		{
//		case 1:
//			calc(Add);
//			break;
//		case 2:
//			calc(Sub);
//			break;
//		case 3:
//			calc(Mul);
//			break;
//		case 4:
//			calc(Div);
//			break;
//		case 0:
//			printf("退出计算器\n");
//			break;
//		default:
//			printf("选择错误, 重新选择\n");
//			break;
//		}
//	} while (input);
//
//	return 0;
//}
//



//
//
//#include <stdio.h>
//
//int Add(int x, int y)
//{
//	return x + y;
//}
//
//int Sub(int x, int y)
//{
//	return x - y;
//}
//
//int Mul(int x, int y)
//{
//	return x * y;
//}
//
//int Div(int x, int y)
//{
//	return x / y;
//}
//
//
//void menu()
//{
//	printf("***************************\n");
//	printf("*****  1. add  2.sub  *****\n");
//	printf("*****  3. mul  4.div  *****\n");
//	printf("*****  0. exit        *****\n");
//	printf("***************************\n");
//}
//
//int main()
//{
//	//函数指针的数组
//	//转移表
//	int (*pfArr[])(int, int) = {0, Add, Sub, Mul, Div};
//
//	int input = 0;
//	int x = 0;
//	int y = 0;
//	int ret = 0;
//
//	do
//	{
//		menu();
//		printf("请选择:>");
//		scanf("%d", &input);
//		if (input >= 1 && input <= 4)
//		{
//			printf("请输入2个操作数:>");
//			scanf("%d %d", &x, &y);
//			ret = pfArr[input](x, y);
//			printf("%d\n", ret);
//		}
//		else if (input == 0)
//		{
//			printf("退出计算器\n");
//		}
//		else
//		{
//			printf("选择错误，重新选择\n");
//		}
//	} while (input);
//
//	return 0;
//}


//void qsort(void* base, //base指向待排序的第一个元素
//          size_t num,  //待排序的元素个数
//          size_t size, //待排序的数组元素的大小，单位是字节
//          int (*compar)(const void*, const void*) //compar是一个函数指针，指向的函数能够比较2个元素
//          );

//qsort函数有4个参数

//void* 是什么？
//是一种指针类型

//int main()
//{
//	int a = 10;
//	int* p = &a;
//	char* pc = &a;//int*---->char*
//
//	void* pv = &a;//int* ----> void*
//	//无具体类型的指针，通用指针类型
//	//void*类型的指针变量，可以接收任意数据类型的地址
//	/*pv+1;
//	*pv;*/
//
//	return 0;
//}
//

//程序员A
//void qsort(void* base, //base指向待排序的第一个元素
//          size_t num,  //待排序的元素个数
//          size_t size, //待排序的数组元素的大小，单位是字节
//          int (*compar)(const void* e1, const void* e2) //compar是一个函数指针，指向的函数能够比较2个元素
//          );
//qsort函数使用的是[快速排序]的思想排序数据的
//排序的算法很多：
//冒泡排序，选择排序，插入排序，希尔排序，快速排序.....
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


//这个函数能够比较e1和e2指向的两个元素，并且给出返回值
//int cmp_int(const void* e1, const void* e2)
//{
//	return *(int*)e1 - *(int*)e2;
//}
//
//void print_arr(int arr[], int sz)
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	printf("\n");
//}
//
////test1测试qsort排序整型数组
//void test1()
//{
//	int arr[] = { 3,1,5,7,2,4,8,6,0,9 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	print_arr(arr, sz);
//	qsort(arr, sz, sizeof(arr[0]), cmp_int);
//	print_arr(arr, sz);
//}
//
//test2测试qsort函数排序结构体数据
struct Stu //学生
{
	char name[20];//名字
	int age;//年龄
};

//假设按照年龄来比较
int cmp_stu_by_age(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}

//strcmp - 是库函数，是专门用来比较两个字符串的大小的

int cmp_stu_by_name(const void* e1, const void* e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}

void test2()
{
	struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };
	int sz = sizeof(s) / sizeof(s[0]);
	//qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}

int main()
{
	test2();
	return 0;
}

//
//
//void print_arr(int arr[], int sz)
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	printf("\n");
//}
//
//
////冒泡排序的思想
////只能排序整型数据
////拓展：能不能让sort函数可以排序任意类型数据呢？
//void sort(int arr[], int sz)
//{
//	int i = 0;
//	//如果要升序
//	for (i = 0; i < sz - 1; i++)
//	{
//		//一趟冒泡排序
//		int j = 0;
//		for (j = 0; j < sz-1-i; j++)
//		{
//			if (arr[j] < arr[j + 1])
//			{
//				int tmp = arr[j];
//				arr[j] = arr[j + 1];
//				arr[j + 1] = tmp;
//			}
//		}
//	}
//}
//
//int main()
//{
//	int arr[] = { 3,1,5,7,2,4,8,6,0,9 };
//	//            0 1
//	//              1 2
//	//10 - 9
//	//9  - 8
//	//8  - 7
//	//
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	sort(arr, sz);
//	print_arr(arr, sz);
//
//	return 0;
//}
//

//int flaot
// 
//结构体类型
//struct Stu //学生
//{
//	char name[20];//名字
//	int age;//年龄
//};
//
//int main()
//{
//	int a = 0;
//	struct Stu s = {"zhangsan", 20};
//	printf("%s %d\n", s.name, s.age);//结构成员访问操作:   结构体变量.成员名
//
//	struct Stu* ps = &s;
//	printf("%s %d\n", (*ps).name, (*ps).age);
//	printf("%s %d\n", ps->name, ps->age);//-> 结构成员访问操作符： 结构体指针->成员名
//
//	return 0;
//}




